package main

import "fmt"

// defer 语句：会将其后面跟随的语句延迟处理

// 多用于资源释放（文件句柄，数据库连接，socket连接）
func deferDemo() {
	fmt.Println("start")
	defer fmt.Println("defer 01")
	defer fmt.Println("defer 02")
	defer fmt.Println("defer 03")
	defer fmt.Println("defer 04")
	defer fmt.Println("defer 05")
	fmt.Println("end")

	/* 打印结果
	start
	end
	defer 05
	defer 04
	defer 03
	defer 02
	defer 01
	*/
}

// Go语言中的return不是原子操作，在底层分为两部分：
// 1.返回值赋值
// 2.真正的RET返回
// 函数中如果存在defer语句，那么defer语句的执行时机在第一和第二步之间

func f1() int { // 1.返回值没有命名，2.执行defer语句操作X，3.返回值赋值返回
	x := 5
	defer func() { // 改的是x不是返回值
		x++
	}()
	return x // 5
}

func f2() (x int) { // 1.返回值有命名x, 2.返回值赋值 5，3.执行defer语句，4.返回
	defer func() {
		x++
	}()
	return 5 // 6
}

func f3() (y int) { // 1.返回值 = y=x=5,返回值是5
	x := 5
	defer func() {
		x++ // 修改的是x 不是返回值
	}()
	return x // 5
}

func f4() (x int) { // 1.返回值 x=5,返回值是5
	defer func(x int) {
		x++ // 修改的是函数中的副本
	}(x)
	return x // 5
}

func main() {
	deferDemo() // 函数调用

}
